// image_utils.cpp
// funciones útiles para menejo de imágenes pgm

#include <string>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <map>
#include "image_utils.h"

using namespace std;

namespace ImageUtils{

  void BasicImageUtils::ImageDimensions(char* image_name, int &width, int &depth){
    string string_aux, aux_width, aux_depth;
    try {
      ifstream image_in(image_name);

      getline(image_in, string_aux); //tipo de imagen P2
      getline(image_in, string_aux); //comentarios
      getline(image_in, string_aux); //tamaño
      istringstream wd(string_aux);
      getline(wd, aux_width, ' ' );
      getline(wd, aux_depth, ' ' );
      width = atoi(aux_width.c_str());
      depth = atoi(aux_depth.c_str());
    } catch(string open_file_error) {
      cerr << "ERROR al intentar abrir imagen" << endl;
    }
  }

  void BasicImageUtils::Map(char* image_name, int **mapa){
    string string_aux, width, depth;
    int i,j, int_width;
    try {
      ifstream image_in(image_name);
      getline(image_in, string_aux); //tipo de imagen P2
      getline(image_in, string_aux); //comentarios
      getline(image_in, string_aux); //tamaño
      istringstream wd(string_aux);
      getline(wd, width, ' ' ); //width
      getline(wd, depth, ' ' ); //depth
      j = 0;
      int_width = atoi(width.c_str());
      //      cout << "MAPA \t" << width << "\t" << depth << "\n";
      getline(image_in, string_aux); //valor máximo
      getline(image_in, string_aux); //primer bit
      while (string_aux != ""){
	//cout << "string_aux \t " << string_aux<< "\n";
	for (i=0; i < int_width; i++){
	  mapa[i][j]= atoi(string_aux.c_str());
	  mapa[i][j]= mapa[i][j]/16;
	  mapa[i][j]= abs(mapa[i][j]-15);
	  getline(image_in, string_aux);
	  //cout << "i: " << i << "j: " << j << "   [i][j] "<< mapa[i][j]<<endl;
	}
	j++;
      }

    } catch(string open_file_error) {
      cerr << "ERROR al manipular imagen" << endl;
    }
  }

  map<pair<int,int>, int> BasicImageUtils::MapAndDimensions(char* image_name, int &width, int &depth){

    string string_aux, aux_width, aux_depth;
    int x,y;
    map<pair<int,int>, int> mapa;
    try {
      ifstream image_in(image_name);
      getline(image_in, string_aux); //tipo de imagen P2
      getline(image_in, string_aux); //comentarios
      getline(image_in, string_aux); //tamaño
      istringstream wd(string_aux);
      getline(wd, aux_width, ' ' ); //width
      getline(wd, aux_depth, ' ' ); //depth
      width = atoi(aux_width.c_str()); //guardamos width
      depth = atoi(aux_depth.c_str()); //guardamos depth
      y = 0;
      getline(image_in, string_aux); //valor máximo
      getline(image_in, string_aux); //primer bit
      while (string_aux != ""){
	//cout << "string_aux \t " << string_aux<< "\n";
	for (x=0; x<width; x++){
	  mapa[make_pair(x,y)]= atoi(string_aux.c_str());
	  mapa[make_pair(x,y)]= mapa[make_pair(x,y)]/16;
	  mapa[make_pair(x,y)]= abs(mapa[make_pair(x,y)]-15);
	  getline(image_in, string_aux);
	  //cout << "i: " << i << "j: " << j << "   [i][j] "<< mapa[i][j]<<endl;
	}
	y++;
      }

    } catch(string open_file_error) {
      cerr << "ERROR al manipular imagen" << endl;
    }
    return mapa;
  }

  map<pair<int,int>, int> BasicImageUtils::Map(char* image_name){

    string string_aux, width, depth;
    int x,y, int_width;
    map<pair<int,int>, int> mapa;
    try {
      ifstream image_in(image_name);
      getline(image_in, string_aux); //tipo de imagen P2
      getline(image_in, string_aux); //comentarios
      getline(image_in, string_aux); //tamaño
      istringstream wd(string_aux);
      getline(wd, width, ' ' ); //width
      getline(wd, depth, ' ' ); //depth
      y = 0;
      int_width = atoi(width.c_str());
      //      cout << "MAPA \t" << width << "\t" << depth << "\n";
      getline(image_in, string_aux); //valor máximo
      getline(image_in, string_aux); //primer bit
      while (string_aux != ""){
	//cout << "string_aux \t " << string_aux<< "\n";
	for (x=0; x<int_width; x++){
	  mapa[make_pair(x,y)]= atoi(string_aux.c_str());
	  mapa[make_pair(x,y)]= mapa[make_pair(x,y)]/16;
	  mapa[make_pair(x,y)]= abs(mapa[make_pair(x,y)]-15);
	  getline(image_in, string_aux);
	  //cout << "i: " << i << "j: " << j << "   [i][j] "<< mapa[i][j]<<endl;
	}
	y++;
      }

    } catch(string open_file_error) {
      cerr << "ERROR al manipular imagen" << endl;
    }
    return mapa;
  }

  void BasicImageUtils::PrintMap(int **mapa, char* image_name, int width, int depth){
    try{
      ofstream image_out(image_name);
      image_out << "P2" << endl;
      image_out << "# Image create for ImageUtils"<< endl;
      image_out << width << " " << depth << endl;
      image_out << "15" << endl;

      for(int y=0;y<depth;y++){
	for(int x=0;x<width;x++){
	  if (mapa[x][y] < 0)
	    image_out << "0" << endl;
	  else
	    image_out << abs(mapa[x][y]-15) << endl;
	}
      }
    } catch (string write_file_error){
      cerr << "ERROR al almacenar la imagen" << endl;
    }
  }

  void BasicImageUtils::PrintMap(int **mapa, int width, int depth){
    try{
      ofstream image_out("image_out.pgm");
      image_out << "P2" << endl;
      image_out << "# Image create for ImageUtils"<< endl;
      image_out << width << " " << depth << endl;
      image_out << "15" << endl;

      for(int i=0;i<depth;i++){
	for(int j=0;j<width;j++){
	  if (mapa[j][i] < 0)
	    image_out << "0" << endl;
	  else
	    image_out << abs(mapa[j][i]-15) << endl;
	}
      }
    } catch (string write_file_error){
      cerr << "ERROR al almacenar la imagen" << endl;
    }
  }

  void BasicImageUtils::PrintMap(map<pair<int,int>, int> mapa,
				 char* image_name, int width, int depth){
    try{
      ofstream image_out(image_name);
      image_out << "P2" << endl;
      image_out << "# Image create for ImageUtils"<< endl;
      image_out << width << " " << depth << endl;
      image_out << "15" << endl;

      for(int y=0;y<depth;y++){
	for(int x=0;x<width;x++){
	  image_out << abs(mapa[make_pair(x,y)]-15) << endl;
	}
      }
    } catch (string write_file_error){
      cerr << "ERROR al almacenar la imagen" << endl;
    }
  }


}

